//
//  NTAVManager.m
//  AVManagerTest
//
//  Created by Henry Borja on 2/4/11.
//  Copyright 2011 Nanotalons LLC. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are met:
//  * Redistributions of source code must retain the above copyright
//  notice, this list of conditions and the following disclaimer.
//  * Redistributions in binary form must reproduce the above copyright
//  notice, this list of conditions and the following disclaimer in the
//  documentation and/or other materials provided with the distribution.
//  * Neither the name of Nanotalons LLC. nor the
//  names of its contributors may be used to endorse or promote products
//  derived from this software without specific prior written permission.
//  
//  THIS SOFTWARE IS PROVIDED BY Nanotalons LLC. "AS IS" AND ANY
//  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
//  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
//  DISCLAIMED. IN NO EVENT SHALL Nanotalons LLC. BE LIABLE FOR ANY
//  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
//  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
//  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
//  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
//  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//  

#import "NTAVManager.h"

#define		kIndexName						 0
#define		kIndexExtension					 1
#define		kTopOfQueue						 0

#define		kTidyUpIntervalDefaultSec		60.0			// If the last time an AV object was used is greater than this interval remove it from memory


static NTAVManager *sharedInstance = NULL;

@implementation NTAVManager

@synthesize delegate, tidyUpInterval;

-(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
	if ([_avQueue count] == kTopOfQueue) {
		[delegate performSelector:@selector(audioPlayerDidFinishPlaying: successfully:) withObject: player withObject: [NSNumber numberWithBool:flag]];
	}
	else {
		[self playQueue];
	}

}

+(NTAVManager *)sharedInstance
{
	@synchronized(self)
	{
		if (sharedInstance == NULL) {
			sharedInstance = [[self alloc] init];
		}
	}
	return(sharedInstance);
}

-(id)init
{
	self = [super init];
	if (self) {
		_avPlayers				= [[NSMutableDictionary alloc] init];
		_avQueue				= [[NSMutableArray alloc] init];
		_avPlayersLastAccessed	= [[NSMutableDictionary alloc] init];
		
		tidyUpInterval			= [[NSNumber alloc] initWithFloat:kTidyUpIntervalDefaultSec];
	}
	return self;
}

-(AVAudioPlayer *)getAVPlayerByFileName:(NSString *) name
{
	_avPlayer = [_avPlayers objectForKey:name];
	if (_avPlayer == nil) {
		NSString *path;
		NSArray *splitName = [name componentsSeparatedByString:@"."];
		
		path = [[NSBundle mainBundle] pathForResource:[splitName objectAtIndex:kIndexName] ofType:[splitName objectAtIndex:kIndexExtension]];  
		_avPlayer =[[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL] autorelease];  
		
		_avPlayer.delegate = self;
		
		[_avPlayers setObject:_avPlayer forKey:name];
	}
	NSNumber *time = [[[NSNumber alloc]initWithDouble:CFAbsoluteTimeGetCurrent()] autorelease];
	[_avPlayersLastAccessed setObject:time forKey:name];

	return _avPlayer;
}

-(void)playAudioByFileName:(NSString *) name
{
	_avPlayer = [self getAVPlayerByFileName:name];	
	[_avPlayer play];
}

-(void)addToQueueAudioByFileName:(NSString *) name
{
	_avPlayer = [self getAVPlayerByFileName:name];
	[_avQueue addObject:_avPlayer];
}

-(void)playQueue
{
	_avPlayer = [_avQueue objectAtIndex:kTopOfQueue];
	[_avQueue removeObjectAtIndex:kTopOfQueue];
	[_avPlayer play];
}

-(void)tidyUpMemory
{
	NSNumber *time = [[NSNumber alloc]initWithDouble:CFAbsoluteTimeGetCurrent()];
	NSMutableArray *objectsToRemove = [[NSMutableArray alloc] init];
	
	for (NSString *item in _avPlayersLastAccessed) {
		if ([time doubleValue]-[[_avPlayersLastAccessed valueForKey:item] doubleValue] > [tidyUpInterval doubleValue]) {
			[objectsToRemove addObject:item];
		}
	}
	
	//Remove the objects
	
	for (NSString *key in objectsToRemove) {
		[_avPlayers removeObjectForKey:key];
		[_avPlayersLastAccessed removeObjectForKey:key];

		NSLog(@"Removed objects at the request of tidyUP object name = %@", key);

	}
	
	[time release];
	[objectsToRemove removeAllObjects];
	[objectsToRemove release];
}

-(void)flushMemory
{
	NSLog(@"AVManager Flushed all objects");
	[_avPlayers removeAllObjects];
}

-(void)dealloc
{
	// iterate through the dictionary and delete all the entries of audio...
	
	[_avPlayers removeAllObjects];
	[_avPlayers release];
	
	[_avQueue removeAllObjects];
	[_avQueue release];
	
	[tidyUpInterval release];
	[super dealloc];
}

@end
